﻿//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//    Crolengi, this program (a part of program) is gameengine based on C++\Directx
//    Copyright (C) 2008 Pashinin Anton Alekseevich (Crol)
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
//    (INCLUDING NEGLIGENCE OR OTHERWISE) 
//    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
//    EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//    Contacts: 
//    Mail: crolengi@gmail.com
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef  CCamera_h
#define  CCamera_h

#include <d3d9.h>
#include <d3dx9.h>

#include "..\\import\\CRLEngi_strings_lib\\CRLEngi_strings.h"
#include "..\\import\\param_trees_lib\\param_trees.h"

#include "include\\Utils\\DrawingFunctions.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// 
/////   :: КЛАСС КАМЕРЫ ::
///// 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CLREngi_Camera{
public:
	CRLEngi_string  CameraName;
	float           MoveSpeed;
	D3DXVECTOR3     Position,Look;
	D3DXVECTOR3     Up,Right;

	D3DXMATRIX      CamMatrix;
	D3DXMATRIX      CamView;
	D3DXMATRIX      CamProjection;

	D3DXMATRIXA16          *matWorld;       // копия мировой 

	bool RightLock;

public:
//#################################################################################################################
	///////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////                                                   Установка параметров из структуры
	bool           Camera_setup(CRLEngi_string CamName,DynamicRow   *row){

		MoveSpeed = 0.1;
		Position.x = Position.y = Position.z = 0;
		Look.x = Look.y = Look.z = 0;	
		Right.x = Right.y = Right.z = 0;	
		Right.z = 1;
		Up.x = Up.y = Up.z = 0;	
		Up.y = 1;		

		CRLEngi_string buffer,chk;
		CameraName = CamName; 
		int id2;
		int	id    = (*row).iLookId(CamName);
		int count = (*row).iCountParams(id) + (*row).iCountKnots(id);
		if (id>0)
		  if (count>0){
			  id = (*row).TopId(id);
			  while (id !=0){

				  buffer = (*row).iLookName(id);
                  // позиция камеры
				  if (buffer=="_POSITION_"){
					id2 = id;
					count = (*row).iCountParams(id);
					if (count >= 3){
					    id2 = (*row).TopId(id2);
						   Position.x = ((*row).iLookName(id2)).toFloat();
						id2 = (*row).NextId(id2);
						   Position.y = ((*row).iLookName(id2)).toFloat();
						id2 = (*row).NextId(id2);
						   Position.z = ((*row).iLookName(id2)).toFloat();
					   }
				    } else 
                  // направление камеры
				  if (buffer=="_LOOK_"){
					  id2 = id;
					  count = (*row).iCountParams(id);
					  if (count >= 3){
					    id2 = (*row).TopId(id2);
						   Look.x = ((*row).iLookName(id2)).toFloat();
						id2 = (*row).NextId(id2);
						   Look.y = ((*row).iLookName(id2)).toFloat();
						id2 = (*row).NextId(id2);
						   Look.z = ((*row).iLookName(id2)).toFloat();
					   }
				  } else 
                  // Up камеры
				  if (buffer=="_UP_"){
					  id2 = id;
					  count = (*row).iCountParams(id);
					  if (count >= 3){
					    id2 = (*row).TopId(id2);
						   Up.x = ((*row).iLookName(id2)).toFloat();
						id2 = (*row).NextId(id2);
						   Up.y = ((*row).iLookName(id2)).toFloat();
						id2 = (*row).NextId(id2);
						   Up.z = ((*row).iLookName(id2)).toFloat();
					   }
				  } else 
                  //  Right камеры
				  if (buffer=="_RIGHT_"){
					  id2 = id;
					  count = (*row).iCountParams(id);
					  if (count >= 3){
					    id2 = (*row).TopId(id2);
						   Right.x = ((*row).iLookName(id2)).toFloat();
						id2 = (*row).NextId(id2);
						   Right.y = ((*row).iLookName(id2)).toFloat();
						id2 = (*row).NextId(id2);
						   Right.z = ((*row).iLookName(id2)).toFloat();
					   }
				  }else //MoveSpeed
				  if (buffer=="_MOVESPEED_"){
					  id2 = id;
					  count = (*row).iCountParams(id);
					  if (count >= 1){
					    id2 = (*row).TopId(id2);
						   MoveSpeed = ((*row).iLookName(id2)).toFloat();
					   }
				  }



				  id = (*row).NextId(id);
			      }
			  
			  //D3DXMatrixTranslation(matWorld,Position.x,Position.y,Position.z);	
			  //D3DXMatrixTranslation(&CamMatrix,Position.x,Position.y,Position.z);	
			  D3DXMatrixLookAtLH( &CamView, &Position, &Look, &Up );
			  D3DXMatrixPerspectiveFovLH( &CamProjection, D3DX_PI/4, 4.0f / 3.0f, 1.0f, 55000.0f );



			  return true;
		      }

			  //buffer = (*row).
	 return false;
	
	}	
	///////////////////////////////////////////////////////////////////////////////////////////////////
	///////////////                                                            Получение матриц камеры
	void           Get_Matrix(LPDIRECT3DDEVICE9 *Device){

	//(*Device)->GetTransform(D3DTS_WORLD,&CamMatrix);
	(*Device)->SetTransform(D3DTS_WORLD,&CamMatrix );
	//(*Device)->SetTransform(D3DTS_WORLD,matWorld );
	


    D3DXMATRIXA16 matView;
    D3DXMatrixLookAtLH( &matView, &Position, &Look, &Up );
    (*Device)->SetTransform( D3DTS_VIEW, &matView );
	CamView = matView;

    D3DXMATRIXA16 matProj;
	// перспектива и дальность  вида
    D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 4.0f / 3.0f, 1.0f, 55000.0f );
	(*Device)->SetTransform( D3DTS_PROJECTION, &matProj );
    CamProjection = matProj;

	if(RightLock){
	////////////// корректируем вектор бока		
		D3DXVECTOR3 N,N90;
		N.x =  Look.x-Position.x;
		N.y =  Look.y-Position.y;
		N.z =  Look.z-Position.z;

		D3DXVec3Normalize(&N,&N);

		N90.x =  -N.z;
		N90.y =  -N.y;
		N90.z =   N.x;

		Right.x = N90.x;
		Right.y = 0.0;
		Right.z = N90.z;

		D3DXVec3Normalize(&Right,&Right);	
	}
}
	///////////////////////////////////////////////////////////////////////////////////////////////////
	D3DXVECTOR3*   GetRight(){
	  return &Right;
	  }
	D3DXVECTOR3*   GetUp(){
	  return &Up;
	  }
	D3DXVECTOR3*   GetPosition(){
	  return &Position;
	  }
	D3DXVECTOR3*   GetLook(){
	  return &Look;
	  }
	///////////////////////////////////////////////////////////////////////////////////////////////////
	///////////////                                                             Получение имени камеры
	CRLEngi_string GetName(){
	  return CameraName;
	  }
	///////////////////////////////////////////////////////////////////////////////////////////////////
	///////////////                                                                    Движение камеры
	void		CameraMoveFull(D3DXVECTOR3 move){
	  Position.x += move.x;
	  Position.y += move.y;
	  Position.z += move.z;

	  Look.x += move.x;
	  Look.y += move.y;
	  Look.z += move.z;
	  }
	void		CameraMove(D3DXVECTOR3 move){
	  Position.x += move.x;
	  Position.y += move.y;
	  Position.z += move.z;
	  }
	void		CameraLookAt(D3DXVECTOR3 move){
	  Look.x = move.x;
	  Look.y = move.y;
	  Look.z = move.z;	
	  }
	void		CameraPointMove(D3DXVECTOR3 move){
	  Look.x += move.x;
	  Look.y += move.y;
	  Look.z += move.z;	
	  }
	///////////////////////////////////////////////////////////////////////////////////////////////////
	///////////////                                                                   Рисование камеры
	
	
	void		Get_PrimitiveDrawing(LPDIRECT3DDEVICE9 *Device){
        //(*Device)->GetTransform(D3DTS_WORLD,&CamMatrix);

        (*Device)->SetTransform(D3DTS_WORLD,&CamMatrix );

		drawLine(Position,Look,Device);

		D3DXVECTOR3 N,N90,CamLook;
		N.x =  Look.x-Position.x;
		N.y =  Look.y-Position.y;
		N.z =  Look.z-Position.z;

		D3DXVec3Normalize(&N,&N);

		CamLook.x = (float)(Position.x+(0.2*N.x));
		CamLook.y = (float)(Position.y+(0.2*N.y));
		CamLook.z = (float)(Position.z+(0.2*N.z));


		N90.x =  -N.z;
		N90.y =  -N.y;
		N90.z =   N.x;

		//Right.x = N90.x;
		//Right.y = 0.0;
		//Right.z = N90.z;

		//D3DXVec3Normalize(&Right,&Right);

	D3DXVECTOR3 v1( 0.0f, 0.0f,0.0f );
    D3DXVECTOR3 v2( 0.0f, 0.0f,0.0f );
    D3DXVECTOR3 v3( 0.0f, 0.0f,0.0f );
	D3DXVECTOR3 v4( 0.0f, 0.0f,0.0f );
/*
 
	v1.x = (CamLook.x)+(80.0*N90.x); 
	v1.y = (CamLook.y);//+(0.5*N90.y);
	v1.z = (CamLook.z)+(10.0*N90.z);

	v2.x = (CamLook.x); //+ (Look.y) + (Look.z);
	v2.y = (CamLook.y); //+ (Look.y) + (Look.z);
	v2.z = (CamLook.z); //+ (Look.y) + (Look.z);

	v3.x = (CamLook.x)-(10.0*N90.x); 
	v3.y = (CamLook.y);//-(0.5*N90.y);
	v3.z = (CamLook.z)-(80.0*N90.z);

	drawLine(v1,v2,Device);
	drawLine(v3,v2,Device);
	drawLine(v1,Position,Device);
	drawLine(v3,Position,Device);

	drawLine(v1,v3,Device);*/

///cube
	v1.x = (float)(Look.x+2.0);
	v1.y = (float)(Look.y+2.0);
	v1.z = (float)(Look.z+2.0);

	v2.x = (float)(Look.x-2.0);
	v2.y = (float)(Look.y-2.0);
	v2.z = (float)(Look.z-2.0);
	
	drawBox(v1,v2,Device);

	v1.x = (float)(Position.x+10.0);
	v1.y = (float)(Position.y+10.0);
	v1.z = (float)(Position.z+10.0);

	v2.x = (float)(Position.x-10.0);
	v2.y = (float)(Position.y-10.0);
	v2.z = (float)(Position.z-10.0);
	
	drawBox(v1,v2,Device);



	}
//#################################################################################################################
public:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                     КОНСТРУКТОР
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	CLREngi_Camera(D3DXMATRIXA16      *World){ 
		RightLock = true;

		matWorld = World;       // копия мировой 
		//CamMatrix= *World;

		D3DXMatrixIdentity(&CamMatrix);

	
	};

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                       ДЕСТРУКТОР
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual ~CLREngi_Camera(){
	};

};

#endif 